package utility

import (
	"context"
	"encoding/json"
	"mldong/api/base"
	"mldong/internal/consts"
	"strings"

	"regexp"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
)

/***
 * 获取查询参数
 * @param ctx
 * @return g.Map
 */
func GetQueryParamMap(ctx context.Context) g.Map {
	// 初始化一个空的 g.Map
	filteredMap := make(g.Map)

	// 获取原始请求体
	body := g.RequestFromCtx(ctx).GetBody()
	if len(body) == 0 {
		return filteredMap
	}

	// 解析 JSON 请求体
	var paramMap g.Map
	if err := json.Unmarshal(body, &paramMap); err != nil {
		g.Log().Debugf(ctx, "解析请求参数失败: %v, 原始数据: %s", err, string(body))
		return filteredMap
	}

	// 过滤出 m_ 开头的 key
	for key, value := range paramMap {
		if len(key) > 2 && key[:2] == "m_" {
			filteredMap[key] = value
		}
	}

	return filteredMap
}

// 字段名安全校验正则
var fieldRegex = regexp.MustCompile(`^(?:[a-zA-Z][a-zA-Z0-9_]*\.)?[a-zA-Z][a-zA-Z0-9_]*$`)

// 检查字段名是否安全
func IsFieldSafe(field string) bool {
	return fieldRegex.MatchString(field)
}

/**
 * 构建查询条件
 * @param pageParam 分页查询对象
 * @param model 查询模型
 * @return *gdb.Model
 */
func BuildQuery(pageParam base.PageParam, model *gdb.Model) *gdb.Model {
	// 直接使用 QueryParamMap 中的参数
	params := pageParam.QueryParamMap
	if params == nil {
		return model
	}

	// 遍历所有 m_ 参数
	for key, value := range params {
		// 解析条件类型和字段名 (格式: m_[type]_[column])
		parts := gstr.Split(key, "_")
		if len(parts) < 3 {
			continue
		}

		// 处理有表别名的情况 (m_t_EQ_id)
		var (
			conditionType string
			column        string
			tableAlias    string
		)

		if len(parts) == 4 {
			// 格式: m_[alias]_[type]_[column]
			tableAlias = parts[1] + "."
			conditionType = parts[2]
			column = tableAlias + gstr.CaseSnake(parts[3])
		} else {
			// 格式: m_[type]_[column]
			conditionType = parts[1]
			column = gstr.CaseSnake(parts[2])
		}

		// 根据条件类型构建查询
		switch conditionType {
		case "EQ":
			model = model.Where(column+" = ?", value)
		case "NE":
			model = model.Where(column+" != ?", value)
		case "GT":
			model = model.Where(column+" > ?", value)
		case "GE":
			model = model.Where(column+" >= ?", value)
		case "LT":
			model = model.Where(column+" < ?", value)
		case "LE":
			model = model.Where(column+" <= ?", value)
		case "LIKE":
			model = model.WhereLike(column, "%"+gconv.String(value)+"%")
		case "NLIKE":
			model = model.WhereNotLike(column, gconv.String(value))
		case "LLIKE":
			model = model.WhereLike(column, "%"+gconv.String(value))
		case "RLIKE":
			model = model.WhereLike(column, gconv.String(value)+"%")
		// 修改后的IN/NIN/BT条件处理逻辑
		case "IN", "NIN":
			var arr []interface{}
			switch v := value.(type) {
			case string:
				if gstr.Contains(v, ",") {
					arr = gconv.Interfaces(gstr.Split(v, ","))
				} else {
					arr = []interface{}{v}
				}
			case []interface{}:
				arr = v
			default:
				// 单个值也转为数组
				arr = []interface{}{value}
			}
			if len(arr) > 0 {
				if conditionType == "IN" {
					model = model.WhereIn(column, arr)
				} else {
					model = model.WhereNotIn(column, arr)
				}
			}

		case "BT":
			var values []interface{}
			switch v := value.(type) {
			case string:
				if gstr.Contains(v, ",") {
					values = gconv.Interfaces(gstr.Split(v, ","))
				}
			case []interface{}:
				values = v
			}

			if len(values) == 2 {
				model = model.WhereBetween(column, values[0], values[1])
			}
		}
	}
	// 2. 处理关键词搜索 (keywords + searchKeys)
	if pageParam.Keywords != "" && pageParam.SearchKeys != "" {
		searchKeys := gstr.Split(pageParam.SearchKeys, ",")
		if len(searchKeys) > 0 {
			// 直接构建OR条件数组
			conditions := make([]string, 0)
			params := make([]interface{}, 0)
			for _, key := range searchKeys {
				safeKey := gstr.CaseSnake(key)
				if !IsFieldSafe(safeKey) {
					continue // 跳过不安全的字段名
				}
				conditions = append(conditions, safeKey+" LIKE ?")
				params = append(params, "%"+pageParam.Keywords+"%")
			}
			model = model.Where("("+gstr.Join(conditions, " OR ")+")", params...)
		}
	}

	// 3. 处理排序 (orderBy)
	if pageParam.OrderBy != "" {
		orderItems := gstr.Split(pageParam.OrderBy, ",")
		for _, item := range orderItems {
			item = gstr.Trim(item)
			parts := gstr.Split(item, " ")
			if len(parts) == 0 {
				continue
			}

			// 校验字段名安全性
			column := gstr.CaseSnake(parts[0])
			if !IsFieldSafe(column) {
				continue
			}
			if len(parts) == 1 {
				// 默认升序排序
				column := gstr.CaseSnake(parts[0])
				model = model.OrderAsc(column)
			} else if len(parts) == 2 {
				column := gstr.CaseSnake(parts[0])
				direction := gstr.ToLower(parts[1])

				if direction == "desc" || direction == "descend" {
					model = model.OrderDesc(column)
				} else {
					model = model.OrderAsc(column)
				}
			}
		}
	}

	return model
}

// 处理分页查询参数
func HandlePageParam(pageParam *base.PageParam) {
	if pageParam.PageNum == nil {
		defaultPageNum := consts.DefaultPageNum
		pageParam.PageNum = &defaultPageNum
	}
	if pageParam.PageSize == nil {
		defaultPageSize := consts.DefaultPageSize
		pageParam.PageSize = &defaultPageSize
	}
}

// 校验唯一性
// model: 数据库模型
// column: 列名(支持表别名)
// value: 要校验的值
// id: 当前记录ID(更新时使用)
// errorMsg: 不唯一时的错误信息
func CheckUnique(model *gdb.Model, column string, value interface{}, id interface{}, errorMsg string) error {

	// 构建查询条件
	m := model.Clone()
	column = gstr.CaseSnake(column)
	m = m.Where(column+" = ?", value)

	// 如果是更新操作，排除当前记录
	if id != nil {
		m = m.WhereNot("id", id)
	}

	// 执行查询
	count, err := m.Count()
	if err != nil {
		g.Log().Errorf(context.TODO(), "唯一性校验查询失败: %v", err)
		return nil
	}

	// 如果不唯一则抛出错误
	if count > 0 {
		err = gerror.New(errorMsg)
	}
	return err
}

// Select 通用下拉选择
func Select(ctx context.Context, tableName string, option base.PageParam, modelHandler func(m *gdb.Model) *gdb.Model) ([]base.LabelValueVO, error) {
	HandlePageParam(&option)
	// 基本参数校验
	if tableName == "" {
		return nil, gerror.New("表名不能为空")
	}
	if option.LabelKey == "" {
		option.LabelKey = "name"
	}
	if option.ValueKey == "" {
		option.ValueKey = "id"
	}
	option.LabelKey = gstr.CaseSnake(option.LabelKey)
	option.ValueKey = gstr.CaseSnake(option.ValueKey)
	// 构建基础查询
	model := g.Model(tableName)
	model = BuildQuery(option, model)
	// 应用查询条件
	if modelHandler != nil {
		model = modelHandler(model)
	}

	// 处理排序
	if option.OrderBy != "" {
		model = model.Order(option.OrderBy)
	}

	var records []g.Map

	// 根据包含类型处理不同查询逻辑
	includeType := 0
	if option.IncludeType != nil {
		includeType = *option.IncludeType
	}
	switch includeType {
	case 1: // 包含指定ID并置顶
		var includedRecords []g.Map
		if len(option.IncludeIds) > 0 {
			// 修改后
			allResult, err := model.Clone().WhereIn(option.ValueKey, option.IncludeIds).All()
			if err != nil {
				return nil, err
			}
			includedRecords = gconv.SliceMap(allResult)
		}

		// 查询分页数据
		if *option.PageSize > 0 {
			model = model.Page(*option.PageNum, *option.PageSize)
		}
		allResult, err := model.All()
		if err != nil {
			return nil, err
		}
		records = gconv.SliceMap(allResult)

		// 合并结果并去重
		records = mergeAndDeduplicate(records, includedRecords, option.ValueKey, option.IncludeIds)

	case 2: // 仅包含指定ID
		if len(option.IncludeIds) > 0 {
			allResult, err := model.WhereIn(option.ValueKey, option.IncludeIds).All()
			if err != nil {
				return nil, err
			}
			records = gconv.SliceMap(allResult)
		}

	default: // 默认查询
		if *option.PageSize > 0 {
			model = model.Page(*option.PageNum, *option.PageSize)
		}
		allResult, err := model.All()
		if err != nil {
			return nil, err
		}
		records = gconv.SliceMap(allResult)
	}

	// 转换为LabelValue结构
	result := make([]base.LabelValueVO, 0, len(records))
	for _, record := range records {
		label := gconv.String(record[option.LabelKey])
		value := record[option.ValueKey]

		// 构建扩展字段
		ext := make(g.Map)
		if option.ExtFieldNames != "" {
			// 分割字符串并去除两边空格
			extFields := gstr.SplitAndTrim(option.ExtFieldNames, ",")
			for _, field := range extFields {
				ext[gstr.CaseCamelLower(field)] = record[gstr.CaseSnake(field)]
			}
		}

		// 手机号脱敏处理
		if !isSuperAdmin(ctx) && !hasSensitiveDataPermission(ctx) {
			label = desensitizePhoneIfNeeded(label, option.LabelKey)
			if v, ok := value.(string); ok {
				value = desensitizePhoneIfNeeded(v, option.ValueKey)
			}
			for field, v := range ext {
				if s, ok := v.(string); ok {
					ext[field] = desensitizePhoneIfNeeded(s, field)
				}
			}
		}

		result = append(result, base.LabelValueVO{
			Label: label,
			Value: value,
			Ext:   ext,
		})
	}

	return result, nil
}

// mergeAndDeduplicate 合并记录并去重
func mergeAndDeduplicate(records, includedRecords []g.Map, valueKey string, includeIds []string) []g.Map {
	// 将includeIds转为map方便查找
	idMap := make(map[string]struct{})
	for _, id := range includeIds {
		idMap[id] = struct{}{}
	}

	// 过滤掉records中已存在于includeIds的记录
	filtered := make([]g.Map, 0, len(records))
	for _, record := range records {
		if _, exists := idMap[gconv.String(record[valueKey])]; !exists {
			filtered = append(filtered, record)
		}
	}

	// 合并结果
	return append(includedRecords, filtered...)
}

// desensitizePhoneIfNeeded 手机号脱敏处理
func desensitizePhoneIfNeeded(value, field string) string {
	if strings.ToLower(field) == "mobilephone" && len(value) > 7 {
		return value[:3] + "****" + value[len(value)-4:]
	}
	return value
}

// isSuperAdmin 检查是否是超级管理员
func isSuperAdmin(ctx context.Context) bool {
	// 实现您的权限检查逻辑
	return false
}

// hasSensitiveDataPermission 检查是否有敏感数据权限
func hasSensitiveDataPermission(ctx context.Context) bool {
	// 实现您的权限检查逻辑
	return false
}
